package mts

import (
	"reflect"

	"gitee.com/zibianqu/fyzdb/lib/typed"
	"github.com/mitchellh/mapstructure"
)

var TagName = "fcl"

// mapstructure:",squash" map转结构体，将子级属性提到父级
// mapstructure:",remain" map转结构体，结构体未定义的属性将放到定义remain的map[string]any中
// mapstructure:",omitempty" 这样当这些字段为默认值时，就不会出现在结构的map[string]interface{}中
// mapstructure:"-" 结构体转map 忽略某一个属性
// @link https://darjun.github.io/2020/07/29/godailylib/mapstructure/
func Covert(source, dest any, tagNames ...string) {
	tagName := TagName
	for _, tagName = range tagNames {

	}
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		WeaklyTypedInput: true,
		Result:           &dest,
		TagName:          tagName,
	})
	if err != nil {
		panic(err)
	}
	decoder.Decode(source)
}

func CovertMap[T typed.IntT | typed.UIntT | typed.FloatT | string, V typed.IntT | typed.UIntT | typed.FloatT | string | any](source any, tagNames ...string) map[T]V {
	tagName := TagName
	for _, tagName = range tagNames {

	}
	dest := make(map[T]V)
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		WeaklyTypedInput: true,
		Result:           &dest,
		TagName:          tagName,
	})
	if err != nil {
		panic(err)
	}
	decoder.Decode(source)
	return dest
}

// param  只有一位参数只能是结构体转map
// param 两个参数，其中第二个参数类型为string，为结构体转map，第一个参数为结构体，第二个参数为TagName
// 如果第二个参数类型不为string， 则互相转换
// param 当为三个参数时，第一个参数为结构体，第二个参数为map类型，第三个参数为string类型TagName
func Map2Struct(param ...any) any {
	length := len(param)
	if length < 1 {
		panic("please input param!")
	}
	s1 := param[0]
	//s1vf := reflect.ValueOf(s1)
	var s2 any = nil
	var s3 any = nil
	var dest any = nil
	var tagName = ""
	var destMap = make(map[string]any)
	if length > 1 {
		s2 = param[1]
	}
	s2vf := reflect.ValueOf(s2)
	if length > 2 {
		s3 = param[2]
	}
	s3vf := reflect.ValueOf(s3)
	// 默认
	dest = s2
	if length == 1 {
		dest = destMap
	}
	if length == 2 && s2vf.Kind() == reflect.String {
		tagName = s2.(string)
		dest = destMap
	}
	if length == 3 && s3vf.Kind() == reflect.String {
		tagName = s3.(string)
		dest = s2
	}
	if tagName != "" || length == 1 {
		/*if s1vf.Kind() != reflect.Ptr && s1vf.Kind() != reflect.Struct {
			panic("param error!")
		}
		if s1vf.Kind() == reflect.Ptr {
			s1RealVf := reflect.ValueOf(s1vf.Elem())
			if s1RealVf.Kind() != reflmapstructure
				panic("param error!")
			}
		}*/
	}
	// @link https://darjun.github.io/2020/07/29/godailylib/mapstructure/
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		WeaklyTypedInput: true,
		Result:           &dest,
		TagName:          tagName,
	})
	if err != nil {
		panic(err)
	}
	decoder.Decode(s1)
	return dest
}
